import {Entity} from '../../entity/entity';
import {EntityRef} from '../../entity/entity-ref';
import {DocApi} from '../../entity/doc-api';
import {PageVoService} from '../../service/page-vo.service';
import {ActivatedRoute, Router} from '@angular/router';
import {DocService} from '../../service/doc.service';
import {PageVo} from '../../entity/page-vo';
import {MessageService} from '../../service/message.service';
import {LinkDto} from '../../entity/link-dto';
import {formatDate} from '@angular/common';
import {BaseDocComponent} from '../page-doc/base-doc.component';
import {AlertMessage} from '../../entity/alert-message';
import {EntityUtils} from '../../utils/entity-utils';
import {ParamEntity} from '../../entity/param-entity';

export class BaseApiComponent extends BaseDocComponent {
    /**
     * 当前选中的接口
     */
    api: DocApi;

    /**
     * 实体类参数，需要展示内部结构
     */
    paramEntities: ParamEntity[];

    /**
     * 响应体
     */
    requestBodys: EntityRef[];

    response: EntityRef;

    /**
     * 文档状态： document / curl
     * @type {string}
     */
    status = 'document';

    private entryRefSet: Set<Entity> = new Set();

    constructor(protected pageVoService: PageVoService,
                protected activatedRoute: ActivatedRoute,
                protected router: Router,
                protected docService: DocService,
                protected messageService: MessageService) {
        super(activatedRoute, router, pageVoService, docService, messageService);
    }

    protected onDocReady() {
        this.api = this.docService.getApi(this.apiId);
        this.setDocApiEntity(this.api);
        this.onApiReady();
    }

    protected onApiReady() {
    }

    protected setPageVo(basePageVo: PageVo) {
        if (this.apiVersion) {
            basePageVo.crumbs.push(<LinkDto>{
                text: `${formatDate(this.apiVersion, 'yyyy-MM-dd HH:mm', this.LOCALE)}`,
                // routerLink: ['doc', this.docId, 'v', this.apiVersion],
                frontIcon: 'history'
            });
        }
        if (this.apiId) {
            if (!this.api) {
                this.messageService.add(<AlertMessage>{
                    id: 'api-not-find',
                    type: 'error',
                    html: `<strong>系统错误：</strong>无法找到此接口！`,
                    time: 8
                });
                return;
            }
            basePageVo.crumbs.push(<LinkDto>{
                text: this.api.name
            });
        }
    }

    protected getLeftMenuId() {
        return this.apiId;
    }

    /**
     * 抽取请求中需要展开展示的实体
     * @param {DocApi} api
     */
    private setDocApiEntity(api: DocApi) {
        if (!api) {
            return;
        }
        this.api = api;
        this.requestBodys = [];
        this.paramEntities = [];
        this.response = this.api.response;
        if (!this.api.requestParams) {
            return;
        }
        this.api.requestParams.forEach(param => {
            this.setParamEntity(param, param.name);
            if (param.annotation === '@RequestBody') {
                this.requestBodys.push(param);
            }
        });
        this.entryRefSet.clear();
    }

    private setParamEntity(paramRef: EntityRef, paramName: string) {
        const entity: Entity = this.docService.getEntity(paramRef.entityName);
        if (!entity) {
            return;
        }

        if (entity.primitive || entity.enumerate) {
            return;
        }

        if (entity.collection || entity.map) {
            // 列表 或 Map
            const parameteredEntityRef = entity.parameteredEntityRefs[entity.collection ? 0 : 1];
            if (parameteredEntityRef) {
                this.setParamEntity(parameteredEntityRef, paramName);
                return;
            }
        }

        if (EntityUtils.isPrimitive(entity)) {
            return;
        }

        if (this.entryRefSet.has(entity)) {
            return;
        }
        this.entryRefSet.add(entity);

        // 抽取需要展开的实体
        if (paramRef.annotation !== '@RequestBody') {
            this.paramEntities.push(<ParamEntity>{
                name: paramName,
                entity: entity
            });
        }

        if (!entity.fields) {
            return;
        }
        entity.fields.forEach(field => {
            this.setParamEntity(field, paramName + '.' + field.name);
        });
    }
}
